const fs = require('fs')
const path = require('path')
const vm = require('vm')


function myRequire(fileName){
    // 1.获取绝对路径；
    let absPath = Module._resolveFileName(fileName)
    // 2.缓存读取
    let cacheModule = Module._cache[absPath]
    if(cacheModule) return cacheModule.exports
    console.log(11111)
    // 3.加载没有缓存的模块
    let module = new Module(absPath)
    Module._cache[absPath] = module
    // 4.编译执行
    module.load()
    // 5.返回数据
    return  module.exports
}

// 只考虑 id ，不考虑别的
function Module(id){
    this.id = id
    this.exports = {}
}

Module._resolveFileName = function(fileName){
    // 1.1.获取绝对路径
    let modulePath = path.resolve(__dirname,fileName)
    // 1.2.判断路径对应的内容是否存在；
    if (fs.existsSync(modulePath)) {
        return modulePath
    } else {
        // 1.3.文件定位（只考虑文件模板，不递归上一级）
        let suffixes = Object.keys(Module._extensions)
        for (let i = 0; i < suffixes.length; i++) {
            const suffix = suffixes[i];
            let fullPath = modulePath + suffix
            if (fs.existsSync(fullPath)) {
                return fullPath
            }
        }
    }
    throw new Error(`${fileName} not exists`)
}

// 不考虑 .node
Module._extensions = {
    '.js'(module){
        // 读取、包裹
        let content = fs.readFileSync(module.id,'utf-8')
        content = Module.wrapper[0] + content + Module.wrapper[1]
        // 执行
        let exports = module.exports
        let dirname = path.dirname(module.id)
        let filename = module.id
        const compilerFn = vm.runInThisContext(content)
        compilerFn.call(exports,exports,myRequire,module,filename,dirname) // 所以 nodejs 默认 this 是 {}
    },
    '.json'(module){
        let content = JSON.parse(fs.readFileSync(module.id,'utf-8'))
        module.exports = content
    }
}
Module._cache = {}
Module.prototype.load = function(){
    let extName = path.extname(this.id)
    Module._extensions[extName](this)

}
Module.wrapper = [
    "(function(exports,requrie,module,__filename,__dirname){",
    "})"
]

// 测试代码
let res1 = myRequire('./04.module')
myRequire('./04.module') // 缓存测试
console.log(res1)
let res2 = myRequire('./04.module.json')
console.log(res2)